package com.wendy.common.web.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wendy.common.core.constant.SecurityConstants;
import com.wendy.common.core.domain.AjaxResult;
import com.wendy.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractMappingJacksonResponseBodyAdvice;

import java.util.Optional;

/**
 * 已经找到问题所在的，这个 ResponseBodyAdvice 只支持 @ResponseBody 注解的 controller 方法，
 * 同样，RequestBodyAdvice 只支持带有 @RequestBody 注解的 controller 方法参数的方法，同时上报的数据必须是 json or xml
 *
 * 也就是说，想要用这两个实现 http 内容的加密解密，是很有局限性的。
 * 并不支持表单 post 请求
 * 将对象加入到一个通用对象,那么返回的数据就可以不用再包装一次
 * @Author: ALEX WANG
 * @Date: 2020/3/18 16:35
 */

@ControllerAdvice(basePackages = {"com.wendy"})
@Order(90)
@ConditionalOnProperty(name = "request.response.body",havingValue = "true",matchIfMissing = true )
@Slf4j
public class AddResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {

    @Autowired
    ObjectMapper objectMapper;

    @Override
    protected void beforeBodyWriteInternal(MappingJacksonValue bodyContainer, MediaType contentType, MethodParameter returnType, ServerHttpRequest request, ServerHttpResponse response) {
        try {
            Object value = bodyContainer.getValue();
            if (value instanceof AjaxResult){
                return;
            }
            if (value instanceof R){
                return;
            }
            String fromSource=Optional.ofNullable(request).map(m->m.getHeaders())
                    .map(m->m.getFirst(SecurityConstants.FROM_SOURCE)).orElse("");
            if(SecurityConstants.INNER.equals(fromSource)){
                log.debug("内部访问不处理参数的返回");
                return;
            }

            bodyContainer.setValue(AjaxResult.success(value));
        }  catch (Exception e) {
            e.printStackTrace();
        }
    }
}
